package com.code.stack;

import java.util.Stack;
/**
 * 224.基本计算器——加强版——实现加减乘除
 *
 * 给你一个字符串表达式 s ，请你实现一个基本计算器来计算并返回它的值。
 *
 * 注意:不允许使用任何将字符串作为数学表达式计算的内置函数，比如 eval() 。
 */
class Solution_244_Enhance {
    public int calculate(String s) {
        Stack<Integer> nums = new Stack<>(); // 数字栈
        Stack<Character> ops = new Stack<>(); // 操作员的堆栈
        int num = 0;
        boolean hasNum = false;

        for (char c : s.toCharArray()) {
            if (c >= '0' && c <= '9') {
                num = num * 10 + c - '0'; // 增加数量
                hasNum = true;
            } else {
                if(hasNum) {
                    nums.push(num);
                    num = 0;
                    hasNum = false;
                }

                if (c == '(') {
                    ops.push(c);
                } else if (c == ')') {
                    // 计算括号内的表达式
                    while (ops.peek() != '(') {
                        nums.push(operate(ops.pop(), nums.pop(), nums.pop()));
                    }
                    ops.pop(); // pop '('
                } else if (c == '+' || c == '-' || c == '*' || c == '/') {
                    while (!ops.isEmpty() && shouldCalculate(c, ops.peek())) {
                        nums.push(operate(ops.pop(), nums.pop(), nums.pop()));
                    }
                    ops.push(c);
                }
            }
        }

        // 最后一个数字
        if(hasNum) {
            nums.push(num);
        }

        // 计算所有剩余的操作
        while (!ops.isEmpty()) {
            nums.push(operate(ops.pop(), nums.pop(), nums.pop()));
        }

        return nums.pop();
    }

    // 辅助方法用于应用操作
    private int operate(char op, int b, int a) {
        switch (op) {
            case '+':
                return a + b;
            case '-':
                return a - b;
            case '*':
                return a * b;
            case '/':
                if (b == 0) throw new UnsupportedOperationException("不能除以零");
                return a / b;
        }
        return 0;
    }

    // 辅助方法用以检查优先级以及是否执行操作
    private boolean shouldCalculate(char currentOp, char prevOp) {
        if (prevOp == '(' || prevOp == ')') return false;
        return (currentOp != '*' && currentOp != '/') || (prevOp != '+' && prevOp != '-');
    }


}